from fastapi import APIRouter, HTTPException, status, Depends, Response
from pydantic import BaseModel
from typing import Dict, Any, Optional
from sqlalchemy.orm import Session
from sqlalchemy.exc import SQLAlchemyError
from app.models.tb_bbe_patient_info import TBBBEPatientInfo
from app.utils.database import get_db_session
import logging
import json

# 配置日志
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)

# 创建路由器
router = APIRouter(prefix="/patient-data-orm", tags=["patient_data_orm"])

class PatientDataRequest(BaseModel):
    """患者数据请求模型"""
    data: Dict[str, Any]

class PatientDataUpdateRequest(BaseModel):
    """患者数据更新请求模型"""
    data: Dict[str, Any]

def dict_to_patient_model(data: Dict[str, Any]) -> TBBBEPatientInfo:
    """
    将字典数据转换为TBBBEPatientInfo模型对象
    """
    # 过滤掉模型中不存在的字段
    model_fields = TBBBEPatientInfo.__table__.columns.keys()
    filtered_data = {key: value for key, value in data.items() if key in model_fields}
    
    # 创建模型实例
    patient = TBBBEPatientInfo(**filtered_data)
    return patient

@router.post("/")
async def save_patient_data_orm(request: PatientDataRequest, db: Session = Depends(get_db_session)):
    """
    使用ORM保存患者数据到数据库（支持upsert：如果ID已存在则更新，否则插入）
    
    - 如果指定ID的记录不存在，则创建新记录
    - 如果指定ID的记录已存在，则更新现有记录
    - 成功时返回状态码200
    """
    try:
        # 获取数据
        patient_data = request.data
        
        # 检查必需的'id'字段
        if 'id' not in patient_data and 'ID' not in patient_data:
            raise HTTPException(
                status_code=status.HTTP_400_BAD_REQUEST,
                detail="缺少必需的'id'字段"
            )
            
        # 获取ID
        patient_id = patient_data.get('id') or patient_data.get('ID')
        
        # 检查记录是否已存在
        existing_patient = db.query(TBBBEPatientInfo).filter(TBBBEPatientInfo.id == patient_id).first()
        
        if existing_patient:
            # 如果记录已存在，则更新它
            model_fields = TBBBEPatientInfo.__table__.columns.keys()
            for key, value in patient_data.items():
                if key in model_fields:
                    setattr(existing_patient, key, value)
            
            db.commit()
            db.refresh(existing_patient)
            
            logger.info(f"患者数据更新成功，ID: {patient_id}")
            
            # 返回200状态码表示更新成功
            return Response(
                content=json.dumps({
                    "code": 0,
                    "success": True,
                    "message": "患者数据更新成功",
                    "data": {
                        "id": patient_id
                    }
                }, ensure_ascii=False),
                status_code=status.HTTP_200_OK,
                media_type="application/json"
            )
        else:
            # 如果记录不存在，则创建新记录
            patient = dict_to_patient_model(patient_data)
            db.add(patient)
            db.commit()
            db.refresh(patient)
            
            logger.info(f"患者数据保存成功，ID: {patient_id}")
            
            # 返回200状态码表示创建成功
            return Response(
                content=json.dumps({
                    "success": True,
                    "message": "患者数据保存成功",
                    "data": {
                        "id": patient_id
                    }
                }, ensure_ascii=False),
                status_code=status.HTTP_200_OK,
                media_type="application/json"
            )
    except SQLAlchemyError as e:
        db.rollback()
        logger.error(f"保存/更新患者数据时数据库错误: {str(e)}")
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail=f"保存/更新患者数据时数据库错误: {str(e)}"
        )
    except Exception as e:
        db.rollback()
        logger.error(f"保存/更新患者数据时出错: {str(e)}")
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail=f"保存/更新患者数据时出错: {str(e)}"
        )

@router.put("/{patient_id}", status_code=status.HTTP_200_OK)
async def update_patient_data_orm(patient_id: str, request: PatientDataUpdateRequest, db: Session = Depends(get_db_session)):
    """
    使用ORM更新患者数据
    """
    try:
        # 查找现有患者数据
        patient = db.query(TBBBEPatientInfo).filter(TBBBEPatientInfo.id == patient_id).first()
        
        if not patient:
            raise HTTPException(
                status_code=status.HTTP_404_NOT_FOUND,
                detail=f"未找到ID为 {patient_id} 的患者数据"
            )
        
        # 更新患者数据
        patient_data = request.data
        
        # 更新模型字段
        model_fields = TBBBEPatientInfo.__table__.columns.keys()
        for key, value in patient_data.items():
            if key in model_fields and key != 'id':  # 不更新主键
                setattr(patient, key, value)
        
        # 提交更改
        db.commit()
        db.refresh(patient)
        
        logger.info(f"患者数据更新成功，ID: {patient_id}")
        
        return {
            "success": True,
            "message": "患者数据更新成功",
            "data": {
                "id": patient_id
            }
        }
    except SQLAlchemyError as e:
        db.rollback()
        logger.error(f"更新患者数据时数据库错误: {str(e)}")
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail=f"更新患者数据时数据库错误: {str(e)}"
        )
    except Exception as e:
        db.rollback()
        logger.error(f"更新患者数据时出错: {str(e)}")
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail=f"更新患者数据时出错: {str(e)}"
        )

@router.get("/{patient_id}", status_code=status.HTTP_200_OK)
async def get_patient_data_orm(patient_id: str, db: Session = Depends(get_db_session)):
    """
    使用ORM获取患者数据
    """
    try:
        # 查找患者数据
        patient = db.query(TBBBEPatientInfo).filter(TBBBEPatientInfo.id == patient_id).first()
        
        if not patient:
            raise HTTPException(
                status_code=status.HTTP_404_NOT_FOUND,
                detail=f"未找到ID为 {patient_id} 的患者数据"
            )
        
        # 将模型对象转换为字典
        patient_dict = {}
        model_fields = TBBBEPatientInfo.__table__.columns.keys()
        for field in model_fields:
            patient_dict[field] = getattr(patient, field)
        
        return {
            "success": True,
            "message": "患者数据获取成功",
            "data": patient_dict
        }
    except Exception as e:
        logger.error(f"获取患者数据时出错: {str(e)}")
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail=f"获取患者数据时出错: {str(e)}"
        )